home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / kernel / tty.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  29KB  |  813 lines

  1. /* This file contains the terminal driver, both for the IBM console and regular
  2.  * ASCII terminals.  It is split into two sections, a device-independent part
  3.  * and a device-dependent part.  The device-independent part accepts
  4.  * characters to be printed from programs and queues them in a standard way
  5.  * for device-dependent output.  It also accepts input and queues it for
  6.  * programs. This file contains 2 main entry points: tty_task() and keyboard().
  7.  * When a key is struck on a terminal, an interrupt to an assembly language
  8.  * routine is generated.  This routine saves the machine state and registers
  9.  * and calls keyboard(), which enters the character in an internal table, and
  10.  * then sends a message to the terminal task.  The main program of the terminal
  11.  * task is tty_task(). It accepts not only messages about typed input, but
  12.  * also requests to read and write from terminals, etc. 
  13.  *
  14.  * The device-dependent part interfaces with the IBM console and ASCII
  15.  * terminals.  The IBM keyboard is unusual in that keystrokes yield key numbers
  16.  * rather than ASCII codes, and furthermore, an interrupt is generated when a
  17.  * key is depressed and again when it is released.  The IBM display is memory
  18.  * mapped, so outputting characters such as line feed, backspace and bell are
  19.  * tricky.
  20.  *
  21.  * The valid messages and their parameters are:
  22.  *
  23.  *   HARD_INT:     a character has been typed (character arrived interrupt)
  24.  *   TTY_READ:     a process wants to read from a terminal
  25.  *   TTY_WRITE:    a process wants to write on a terminal
  26.  *   TTY_IOCTL:    a process wants to change a terminal's parameters
  27.  *   TTY_SETPGRP:  indicate a change in a control terminal
  28.  *   CANCEL:       terminate a previous incomplete system call immediately
  29.  *
  30.  *    m_type      TTY_LINE   PROC_NR    COUNT   TTY_SPEK  TTY_FLAGS  ADDRESS
  31.  * |-------------+---------+---------+---------+---------+---------+---------|
  32.  * | HARD_INT    |minor dev|         |         |         |         |         |
  33.  * |-------------+---------+---------+---------+---------+---------+---------|
  34.  * | TTY_READ    |minor dev| proc nr |  count  |         |         | buf ptr |
  35.  * |-------------+---------+---------+---------+---------+---------+---------|
  36.  * | TTY_WRITE   |minor dev| proc nr |  count  |         |         | buf ptr |
  37.  * |-------------+---------+---------+---------+---------+---------+---------|
  38.  * | TTY_IOCTL   |minor dev| proc nr |func code|erase etc|  flags  |         |
  39.  * |-------------+---------+---------+---------+---------+---------+---------|
  40.  * | TTY_SETPGRP |minor dev| proc nr |         |         |         |         |
  41.  * |-------------+---------+---------+---------+---------+---------+---------
  42.  * | CANCEL      |minor dev| proc nr |         |         |         |         |
  43.  * ---------------------------------------------------------------------------
  44.  */
  45.  
  46. #include "kernel.h"
  47. #include <signal.h>
  48. #include <minix/callnr.h>
  49. #include <minix/com.h>
  50. #include <sgtty.h>
  51. #include "proc.h"
  52. #include "tty.h"
  53. #if (CHIP == INTEL)
  54. #include "ttymaps.h"
  55. #endif
  56.  
  57. PUBLIC  void finish();
  58. PUBLIC  void tty_reply();
  59. PUBLIC  void sigchar();
  60. PRIVATE void do_int();
  61. PRIVATE void charint();
  62. PRIVATE void in_char();
  63. PRIVATE void echo();
  64. PRIVATE void do_read();
  65. PRIVATE void do_write();
  66. PRIVATE void do_ioctl();
  67. PRIVATE void do_setpgrp();
  68. PRIVATE void do_cancel();
  69.  
  70. /*===========================================================================*
  71.  *                tty_task                     *
  72.  *===========================================================================*/
  73. PUBLIC void tty_task()
  74. {
  75. /* Main routine of the terminal task. */
  76.  
  77.   message tty_mess;        /* buffer for all incoming messages */
  78.   register struct tty_struct *tp;
  79.  
  80.   output_done = 0;
  81.   tty_init();            /* initialize */
  82.   init_rs232();
  83.   while (TRUE) {
  84.     receive(ANY, &tty_mess);
  85.     tp = &tty_struct[tty_mess.TTY_LINE];
  86.     switch(tty_mess.m_type) {
  87.         case HARD_INT:    do_int();            break;
  88.         case TTY_READ:    do_read(tp, &tty_mess);        break;
  89.         case TTY_WRITE:    do_write(tp, &tty_mess);    break;
  90.         case TTY_IOCTL:    do_ioctl(tp, &tty_mess);    break;
  91.         case TTY_SETPGRP:   do_setpgrp(tp, &tty_mess);    break;
  92.         case CANCEL:    do_cancel(tp, &tty_mess);    break;
  93.         default:        tty_reply(TASK_REPLY, tty_mess.m_source, 
  94.                     tty_mess.PROC_NR, EINVAL, 0L, 0L);
  95.     }
  96.   }
  97. }
  98.  
  99.  
  100. /*===========================================================================*
  101.  *                do_int                         *
  102.  *===========================================================================*/
  103. PRIVATE void do_int()
  104. {
  105. /* The TTY task can generate two kinds of interrupts:
  106.  *    - a character has been typed on the console or an RS232 line
  107.  *    - an RS232 line has completed a write request (on behalf of a user)
  108.  * If either interrupt happens and the TTY task is idle, the task gets the
  109.  * interrupt message immediately and processes it.  However, if the TTY
  110.  * task is busy, a bit is set in 'busy_map' and the message pointer stored.
  111.  * If multiple messages happen, the bit is only set once.  No input data is
  112.  * lost even if this happens because all the input messages say is that there
  113.  * is some input.  The actual input is in the tty_driver_buf array, so losing
  114.  * a message just means that when the one interrupt-generated message is given
  115.  * to the TTY task, it will find multiple characters in tty_driver_buf.
  116.  *
  117.  * The introduction of RS232 lines has complicated this situation somewhat. Now
  118.  * a message can mean that some RS232 line has finished transmitting all the
  119.  * output given to it.  If a character is typed at the instant an RS232 line
  120.  * finishes, one of the two messages may be overwritten because MINIX only
  121.  * provides single buffering for interrupt messages (in proc.c).To avoid losing
  122.  * information, whenever an RS232 line finishes, the flag tty_waiting is set
  123.  * to COMPLETED and kept that way until its completion is processed and a 
  124.  * message sent to FS saying that output is done.  The number of RS232 lines in
  125.  * COMPLETED state is kept in output_done, which is checked on each interrupt,
  126.  * so that a lost HARD_INT line completion interrupt will be quickly
  127.  * recovered.
  128.  *
  129.  * In short, when this procedure is called, it can check for RS232 line done
  130.  * by inspecting output_done and it can check for characters in the input
  131.  * buffer by inspecting tty_driver_buf[0].  Thus losing a message to the TTY
  132.  * task is not serious because the underlying conditions are explicitly checked
  133.  * for on each interrupt.
  134.  */
  135.  
  136.   /* First check to see if any RS232 lines have completed. */
  137.   if (output_done > 0) {
  138.     /* If a message is sent to FS for RS232 done, don't process any input
  139.      * characters now for fear of sending a second message to FS, which 
  140.      * would be lost.
  141.      */
  142.     if (tty_o_done()) {
  143.         return;
  144.     }
  145.   }
  146.   charint();            /* check for input characters */
  147. }
  148.  
  149.  
  150. /*===========================================================================*
  151.  *                charint                         *
  152.  *===========================================================================*/
  153. PRIVATE void charint()
  154. {
  155. /* A character has been typed.  If a character is typed and the tty task is
  156.  * not able to service it immediately, the character is accumulated within
  157.  * the tty driver.  Thus multiple chars may be accumulated.  A single message
  158.  * to the tty task may have to process several characters.
  159.  */
  160.  
  161.   int m, n, count, replyee, caller, old_state;
  162.   char *ptr, *copy_ptr, ch;
  163.   struct tty_struct *tp;
  164.  
  165.   old_state = lock();
  166.   ptr = tty_driver_buf;        /* pointer to accumulated char array */
  167.   copy_ptr = tty_copy_buf;    /* ptr to shadow array where chars copied */
  168.   n = tty_buf_count(ptr);    /* how many chars have been accumulated */
  169.   count = n;            /* save the character count */
  170.   n = n + n;            /* each char occupies 2 bytes */
  171.   ptr += 4;            /* skip count field at start of array */
  172.   while (n-- > 0)
  173.     *copy_ptr++ = *ptr++;    /* copy the array to safety */
  174.   ptr = tty_driver_buf;
  175.   tty_buf_count(ptr) = 0;        /* accumulation count set to 0 */
  176.   restore(old_state);
  177.  
  178.   /* Loop on the accumulated characters, processing each in turn. */
  179.   if (count == 0) return;    /* on HARD_INT interrupt, count might be 0 */
  180.   copy_ptr = tty_copy_buf;
  181.   while (count-- > 0) {
  182.     ch = *copy_ptr++;    /* get the character typed */
  183.     n = *copy_ptr++;    /* get the line numb